<?php
/*
 * Created on 2008. 10. 2.
 * Creator akddd (akdddnet@gmail.com)
 *
 * comment :  Exception 처리 설정
 *   10. 1 : Exception처리를 어떻게 할까 고민중인데... 딱히 획기적인 방법이 생각이 안남. 
 *             숫자 0, 1, 2 를 두고서, 0일때는 화면에 표시, 1일경우에는 로그에만 남고, 2일 경우에는 화면하고 로그 둘다 남김
 *     - 기존 Logger하고 통합 할건지. 아님 따로 관리를 할건지 생각좀 해봐야될듯 한데;;;
 *   
 *     - Exception을 최상위 framework로 빼야될듯... (파일로 출력시키는 부분은 파일명을 받아서 처리하면 될듯, 03:36분 생각;;;)
 *   10. 6 : Exception __fw에서 __framework로 이동. 
 *      
 * 
 *
 *
 * Exception class 형태..
 * Exception {
		protected string $message ;
		private string $string ;
		protected int $code ;
		protected string $file ;
		protected int $line ;
		private array $trace ;
		
		public Exception::__construct ([ string $message=NULL [, int $code=0 ]] )
		final public string Exception::getMessage ( void )
		final public int Exception::getCode ( void )
		final public string Exception::getFile ( void )
		final public string Exception::getLine ( void )
		final public array Exception::getTrace ( void )
		final public string Exception::getTraceAsString ( void )
		public string Exception::__toString ( void )
		final private string Exception::__clone ( void )
	} 
 *
 * 2011. 03. 24
 * 	- 기존에는 cfg, tpl을 global로 끌어와서 프레임워크임에도 프로젝트에 종속적이 되버려서... 파라메터로 전달 받아서 처리 되게 수정함.
 * 	- 시간 적 여유가 되면 좀 더 수정하는게 좋을듯 싶은데... 음...
 */
 	
 	
 	/**
 	 * 확장 Exception
 	 * 
 	 */
 	class AkException extends Exception
 	{
 		// 화면 출력 방법
 		private $printType;
 		private $ect = null;
 		private $logger = null;
 		private $tpl = null;
 		
 		public function __construct($printType = 2, LogAbstract $logger, $tpl = null)
 		{
 			$this->printType = $printType;
 			$this->logger = $logger;
 			
 			if($tpl != null)
 				$this->tpl = $tpl;
 		}
 		
 		/**
 		 * Exception발생시 이 함수가 실행이 됩니다.
 		 * 
 		 * @param object $ect : Exception Object
 		 * @return void;
 		 */
		public function ExceptionHandler(Exception $ect)
		{	
			// Exception 값 셋팅
			$this->ect = $ect;
				
			// exception print type에 따라 출력
			switch($this->printType)
			{
				case 0 :
					$this->DisplayException();
					break;
				case 1 : 
					$this->FileException();
					break;
				case 2 :
					$this->DisplayException();
					$this->FileException();
					break;
			}
			
			exit();
		}
		
		/**
		 * Exception값이 넘어오지 않았을 경우 화면에 표시
		 * 
		 * @param string $str : 화면에 표시할 경고문구
		 * @return string;
		 */
		private function printHTML($str)
		{
			$print =  "<!DOCTYPE html PUBLIC \"-//W3C//DTD XHTML 1.0 Transitional//EN\"
					    \"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd\">
					<html xmlns=\"http://www.w3.org/1999/xhtml\" lang=\"ko\" xml:lang=\"ko\">
					<head>
						<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />
						<title> Exception </title>
						<style type=\"text/css\">
							*{font-size:9pt; font-family:gulim, Tahoma, Verdana, sans-serif;}
							.box {border:1px solid #E0E0E0; background-color:#F6F6F6; margin:10px; padding:10px; overflow:auto; display:none;}
							dt.title{color:red; font-weight:bold; width:100px; float:left;}
							dt.click{text-decoration:underline; cursor:pointer;}
							li {margin-left:40px;}
							fieldset {border:0px; padding:0px; margin:0px;}
							legend {display:none;}
						</style>
						<script language=\"javascript\" type=\"text/javascript\">
							function stack_detail_view()
							{
								d = document.getElementById('stack_detail');
								if(d.style.display == \"block\")
									d.style.display = \"none\";
								else 
									d.style.display = \"block\";
							}
						</script>
					</head>
					
					<body>
						".$str."
					</body>
					</html>";
			return $print;
		}
		
		
		
		
		/**
		 * Exception을 화면에 표시합니다.
		 * 
		 * @return void;
		 */
		protected function DisplayException()
		{
			$time = date('Y-m-d H:i:s', time());
			
			if($this->tpl !== null) {
				$this->tpl->define(array(
					"body"=>"exception.html"
				));
				
				// detiltrace는 통으로 넘겨 주지 맙시다 -0-
				$this->tpl->assign(array(
						 "message"=>$this->ect->getMessage()
						,"file"=>$this->ect->getFile()
						,"line"=>$this->ect->getLine()
						,"trace"=>$this->getSimpleTrace($this->ect->getTrace())
						//,"detailtrace"=>Common::print_r($this->ect, true)
						,"time"=>$time
				));
				
				$this->tpl->print_("main");
				exit;
			} else {
				$print = '<fieldset><legend>'.$time.'</legend>';
				$print .= '<dl>';
				$print .= '    <dt class=\'title\'><strong>Time</strong> : </dt><dd>'.$time.'</dd>';
				$print .= '    <dt class=\'title\'><strong>Message</strong> : </dt><dd><strong>'.$this->ect->getMessage().'</strong></dd>';
				$print .= '    <dt class=\'title\'><strong>File</strong> : </dt><dd>'.$this->ect->getFile().'</dd>';
				$print .= '    <dt class=\'title\'><strong>Line</strong> : </dt><dd>'.$this->ect->getLine().'</dd>';
				$print .= '    <dt class=\'title click\' onclick=\'stack_detail_view()\'><strong>Stack</strong> : </dt><dd>'.$this->getSimpleTrace($this->ect->getTrace()).'<div class=\'box\' id=\'stack_detail\'>'.Common::print_r($this->ect, true).'</div></dd>';
				$print .= '</dl>';
				$print .= '</fieldset>';
				
				echo $this->printHTML($print);
			}
		}
		
		/**
		 * 심플한 stack을 리턴합니다.
		 * 
		 * @param object $e : Exception->getTrace()
		 * @return string $rtn;
		 */
		private function getSimpleTrace($e)
		{
			$rtn = '<ol>';
			foreach($e as $key => $value) {
				if(array_key_exists("file", $value))
					$rtn .= '<li><strong>'.$value['file'].'</strong> ('.$value['line'].' line) </li>';
			}
			$rtn .= '</ol>';
			
			return $rtn;
		}
		
		
		/**
		 * Exception을 파일에 출력합니다.
		 */
		protected function FileException()
		{ 
	        $str = Common::getPrintRtoString($this->ect); 
	        
	        $str = str_replace('\n', '\r\n', $str);
	        $str = str_replace("<br/>", "", $str);
	        $logger = Logger::getInstance();
	        $logger->Write($str, Logger::EMERG); 
		}
 	}